﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;

namespace HeritageAcademy.Library.Controls
{
    public class StretchWrapPanel : Panel
    {
		#region Protected Methods 

        protected override Size ArrangeOverride(Size finalSize)
        {
            int lineCount = 0;
            double lineWidth = 0;
            double lineHeight = 0;

            double top = 0;
            double left = 0;
            double width = 0;
            double height = 0;
            double gap = 0;

            for (int u = 0; u <= this.Children.Count - 1; u++)
            {
                UIElement curr = this.Children[u];
                Size currSize = GetItemDesiredSize(curr);
                lineCount++;

                lineWidth = lineWidth + currSize.Width;
                lineHeight = Math.Max(lineHeight, currSize.Height);

                bool isLast = this.Children[this.Children.Count - 1].Equals(curr);

                if (isLast || (lineWidth + GetItemDesiredSize(this.Children[u + 1]).Width) >= finalSize.Width)
                {
                    gap = (isLast && !this.IsLastRowJustified) ? 0 : lineCount <= 1 ? 0 : (finalSize.Width - lineWidth) / (lineCount - 1);
                    for (int i = (u - lineCount) + 1; i <= u; i++)
                    {
                        UIElement element = this.Children[i];
                        width = GetItemDesiredSize(element).Width;
                        height = GetItemDesiredSize(element).Height;

                        element.Arrange(new Rect(left, top, width, height));

                        left += (width + gap);
                    }

                    top += lineHeight;
                    left = 0;

                    // reset our line markers
                    lineWidth = 0;
                    lineHeight = 0;
                    lineCount = 0;
                }
            }

            return finalSize;
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            double lineWidth = 0;
            double lineHeight = 0;
            double totalWidth = 0;
            double totalHeight = 0;

            Size asBigAsYouWant = new Size(double.PositiveInfinity, double.PositiveInfinity);

            foreach (UIElement element in this.Children)
            {
                element.Measure(asBigAsYouWant);
                Size itemSize = GetItemDesiredSize(element);

                // reset the line if we run out of room
                if ((this.Children[this.Children.Count - 1].Equals(element)) || (lineWidth + GetItemDesiredSize(this.Children[this.Children.IndexOf(element) + 1]).Width > availableSize.Width))
                {
                    if (lineWidth > totalWidth) totalWidth = lineWidth;
                    lineWidth = 0;

                    totalHeight += lineHeight;
                    lineHeight = 0;
                }

                lineWidth += itemSize.Width;

                // take the tallest item in the line as our lineHeight
                if (itemSize.Height > lineHeight) lineHeight = itemSize.Height;
            }

            return new Size(availableSize.Width, totalHeight);
        }

		#endregion Protected Methods 

		#region Private Methods 

        private Size GetItemDesiredSize(UIElement element)
        {
            Size itemSize = new Size();
            itemSize.Width = double.IsInfinity(element.DesiredSize.Width) ? 0 : element.DesiredSize.Width;
            itemSize.Height = double.IsInfinity(element.DesiredSize.Height) ? 0 : element.DesiredSize.Height;
            return itemSize;
        }

		#endregion Private Methods 

        #region IsLastRowJustified

        /// <summary>
        /// IsLastRowJustified Dependency Property
        /// </summary>
        public static readonly DependencyProperty IsLastRowJustifiedProperty =
            DependencyProperty.Register("IsLastRowJustified", typeof(bool), typeof(StretchWrapPanel),
                new FrameworkPropertyMetadata((bool)true));

        /// <summary>
        /// Gets or sets the IsLastRowJustified property.  This dependency property 
        /// indicates ....
        /// </summary>
        public bool IsLastRowJustified
        {
            get { return (bool)GetValue(IsLastRowJustifiedProperty); }
            set { SetValue(IsLastRowJustifiedProperty, value); }
        }

        #endregion
    }
}
